using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using SpellCenter.UI.Properties;
using SpellCore;

namespace SpellCenter.UI
{
    internal partial class SpellStatusEditorControl : UserControl
    {
        private readonly Font _font;
        private SpellGridControl _spellGrid;
        private int _row;
        private bool _editMode;
        private ISpellingChangeManager _progressBar;

        public ISpellingChangeManager ProgressBar
        {
            get
            {
                if (_progressBar == null)
                    throw new InvalidOperationException("ProgressBar must be set before a word is changed"); 
                return _progressBar;
            }
            set { _progressBar = value; }
        }

        public SpellStatusEditorControl()
        {
            InitializeComponent();
            SafeResize(Width);
            _font = new Font(_wordLabel.Font.FontFamily, 22);
            _wordLabel.Font = _font;
            _wordEditBox.Font = _font;

            InitButton(_goodButton);
            InitButton(_questionButton);
            InitButton(_badButton);

            _goodButtonToolTip.SetToolTip(_goodButton, "Spelled correctly (key: 1)");
            _questionButtonToolTip.SetToolTip(_questionButton, "Unsure if this is correct (key: 2)");
            _badButtonToolTip.SetToolTip(_badButton, "Spelled wrong (key: 3)");

            RegisterEvents();
        }

        #region Events

        private void RegisterEvents()
        {
            _wordLabel.Click += WordLabel_Click;
            _wordEditBox.KeyUp += WordEditBox_KeyUp;
            _wordLabel.TextChanged += WordLabel_TextChanged;
        }

        private void WordLabel_TextChanged(object sender, EventArgs e)
        {
            _wordEditBox.Text = _wordLabel.Text;
            ReturnToLable();
        }

        private void WordEditBox_KeyUp(object sender, KeyEventArgs e)
        {
            if(e.KeyCode == Keys.Return)
            {
                // This would be very bad, to allow a user to "delete" words accidentally
                if(_wordEditBox.Text != string.Empty)
                {
                    _spellGrid.Model.ChangeSpelling(_row, _wordEditBox.Text, ProgressBar);
                    _spellGrid.SetDataSource();
                }
                ReturnToLable();
            }
            else if(e.KeyCode == Keys.Escape)
            {
                LoseControl();
            }
        }

        private void LoseControl()
        {
            _wordEditBox.Text = _wordLabel.Text;
            ReturnToLable();
        }

        private void ReturnToLable()
        {
            _editMode = false;
            _wordEditBox.Visible = false;
            _wordLabel.Visible = true;
            _wordLabel.Text = _wordEditBox.Text;
//            _wordEditBox.LostFocus -= WordEditBox_LostFocus;
        }

        private void WordLabel_Click(object sender, EventArgs e)
        {
            _wordLabel.Visible = false;
            _wordEditBox.Text = _wordLabel.Text;
            _wordEditBox.Visible = true;
            _editMode = true;
            _wordEditBox.Focus();
//            _wordEditBox.LostFocus += WordEditBox_LostFocus;
        }

        private void WordEditBox_LostFocus(object sender, EventArgs e)
        {
            LoseControl();
        }

        #endregion

        public bool IsInEditMode
        {
            get { return _editMode; }
        }

        public SpellGridControl SpellGrid
        {
            get { return _spellGrid; }
            set
            {
                if(value != null)
                {
                    _spellGrid = value;
                    _spellGrid.RowChanged += SpellGrid_RowChanged;
                }
            }
        }

        private void SpellGrid_RowChanged(object sender, DataGridViewRowEventArgs e)
        {
            _row = e.Row.Index;
            _wordLabel.Text = SpellGrid.Model.Data[_row].Word;
            SetButtonsAsEnabled(true);
        }

        private void SetButtonsAsEnabled(bool enabled)
        {
            _goodButton.Enabled = enabled;
            _questionButton.Enabled = enabled;
            _badButton.Enabled = enabled;
        }

        private void InitButton(Button button)
        {
            button.Font = _font;
            button.MouseEnter += Buttons_MouseEnter;
            button.MouseLeave += Buttons_MouseLeave;
            button.Click += Buttons_Click;
            button.Enabled = false;
            button.TextAlign = ContentAlignment.MiddleCenter;
        }

        private void Buttons_Click(object sender, EventArgs e)
        {
            Debug.Assert(sender.GetType() == typeof(Button));
            Button button = (Button)sender;
            _spellGrid.Model.Data[_row].Status = ButtonValue(button);
            _spellGrid.MoveToNextRow();
        }

        private CheckingResult ButtonValue(Button button)
        {
            {
                if(button == _goodButton)
                    return CheckingResult.Good;
                if(button == _badButton)
                    return CheckingResult.Bad;
                if(button ==  _questionButton)
                    return CheckingResult.Unknown;
                else
                    return CheckingResult.Unknown;
            }
        }

        private void Buttons_MouseLeave(object sender, EventArgs e)
        {
            Debug.Assert(sender.GetType() == typeof(Button));
            Button button = (Button)sender;
            if (button == _badButton)
            {
                _badButton.Image = Resources.XMark;
            }
            else if (button == _goodButton)
            {
                _goodButton.Image = Resources.CheckMark;
            }
            else if (button == _questionButton)
            {
                _questionButton.Image = Resources.QuestMark;
            }
        }

        private void Buttons_MouseEnter(object sender, EventArgs e)
        {
            Debug.Assert(sender.GetType() == typeof (Button));
            Button button = (Button) sender;
            if(button == _badButton)
            {
                _badButton.Image = Resources.XMark_mouseover;
            }
            else if(button == _goodButton)
            {
                _goodButton.Image = Resources.CheckMark_mouseover;
            }
            else if(button == _questionButton)
            {
                _questionButton.Image = Resources.QuestMark_mouseover;
            }
        }

        public void SafeResize(int width)
        {
            Width = width;
            Height = 50;
            _wordLabel.Width = ClientRectangle.Width - (Height*3);
            _wordLabel.Location = ClientRectangle.Location;
            _wordEditBox.Size = _wordLabel.Size;
            _wordEditBox.Location = _wordLabel.Location;
            
            _goodButton.Size = new Size(ClientRectangle.Height, ClientRectangle.Height);
            _questionButton.Size = new Size(ClientRectangle.Height, ClientRectangle.Height);
            _badButton.Size = new Size(ClientRectangle.Height, ClientRectangle.Height);

            _badButton.Location = new Point(ClientRectangle.Right - _badButton.Width, ClientRectangle.Top);
            _questionButton.Location = new Point(_badButton.Left - _questionButton.Width, ClientRectangle.Top);
            _goodButton.Location = new Point(_questionButton.Left - _goodButton.Width, ClientRectangle.Top);
        }

        public void HandleKeyCode(Keys keyCode)
        {
            switch(keyCode)
            {
                case Keys.D1:
                    Buttons_MouseEnter(_goodButton, EventArgs.Empty);
                    Refresh();
                    Buttons_Click(_goodButton, EventArgs.Empty);
                    Thread.Sleep(30);
                    Buttons_MouseLeave(_goodButton, EventArgs.Empty);
                    break;
                case Keys.D2:
                    Buttons_MouseEnter(_questionButton, EventArgs.Empty);
                    Refresh();
                    Buttons_Click(_questionButton, EventArgs.Empty);
                    Thread.Sleep(30);
                    Buttons_MouseLeave(_questionButton, EventArgs.Empty);
                    break;
                case Keys.D3:
                    Buttons_MouseEnter(_badButton, EventArgs.Empty);
                    Refresh();
                    Buttons_Click(_badButton, EventArgs.Empty);
                    Thread.Sleep(30);
                    Buttons_MouseLeave(_badButton, EventArgs.Empty);
                    break;
            }
        }
    }
}
